Enable background mode lifecycle#4
Closed
Newarr wants to merge 12 commits intofeature/menu-bar-status-itemfrom
Closed
Enable background mode lifecycle#4Newarr wants to merge 12 commits intofeature/menu-bar-status-itemfrom
Newarr wants to merge 12 commits intofeature/menu-bar-status-itemfrom
Conversation
c11552e to
07b634e
Compare
5283cc3 to
3cb882f
Compare
Set LSUIElement=YES so the app runs without a dock icon. Wire MenuBarController into AppDelegate, intercept window close to hide instead of destroy (orderOut), add termination guard that awaits session finalization (30s timeout) before quitting, and show a one-shot notification explaining background mode on first window hide with auto-detect enabled. Window identification uses a static constant (mainWindowID) with exact equality matching instead of substring search.
3cb882f to
f4b4822
Compare
07b634e to
7c582f4
Compare
Add acoustic echo cancellation via Apple Voice Processing. Enables setVoiceProcessingEnabled on AVAudioEngine mic input to cancel speaker echo that causes duplicate transcription. On by default with toggle in Settings > Recording. Closes yazinsai#88
Redesign NotesView: 2-tab model with batch cleanup Replaces the 3-state Raw/Refined/Notes detail view with a clean 2-tab segmented picker (Transcript / Notes). Adds batch transcript cleanup via TranscriptCleanupEngine for on-demand refinement of past sessions. Based on the design direction from @Newarr in PRs yazinsai#82 and yazinsai#83 — thank you for the original work! Reimplemented to keep drain() timeout at 5s and strip unrelated scope changes. Closes yazinsai#82, closes yazinsai#83.
Add structured Markdown meeting output (openoats/v1) Produces `.md` files in ~/Documents/OpenOats/ alongside existing `.txt` output. YAML frontmatter with date, duration, participants, ASR engine, and meeting app. Body sections: Summary, Action Items, Decisions, Transcript (high-signal first). Speaker-attributed transcript lines with relative timestamps. Three processing stages: raw transcript (always written at finalization), LLM-enriched sections inserted when notes are generated. Existing .txt output is preserved unchanged. Includes format specification, example transcript, and 42 unit tests. Closes no issues — new capability.
Derive isRecording from coordinator state machine Replace writable stored `_isRecording` property with a computed property that reads directly from the coordinator's authoritative `MeetingState`. Eliminates stale-value risk from the 100ms polling loop. Also adds `MeetingMetadata.manual()` static factory to deduplicate inline metadata construction across call sites.
Extract service initialization for headless operation Add ensureServicesInitialized() on AppRuntime with an idempotency guard. Coordinator-owned services (TranscriptionEngine, TranscriptLogger, RefinementEngine, AudioRecorder) are created on first call from wherever runs first. ContentView.task now only creates view-local services (KnowledgeBase, SuggestionEngine) that don't need to outlive the window.
…ement LSUIElement=YES makes the app a permanent accessory with no menu bar or dock icon. Toggle to .regular on launch and window show, .accessory on window close. Standard pattern used by Bartender, MonitorControl, etc.
Add clearModelCache() to TranscriptionBackend protocol so corrupt model files are removed on load failure. Each backend (Parakeet, Qwen3, WhisperKit) implements targeted cache deletion. TranscriptionEngine now clears cache and resets download state on failure, so "Download Now" triggers a fresh download.
Add horizontal wordmark logo (icon + text) for marketing and documentation use. Contributed by @Alex-Wengg.
…yazinsai#95) (yazinsai#103) Fix mic tap format failure and AEC conflict with system audio capture. Based on analysis from @brandonbloom in yazinsai#95.
* Derive isRecording from coordinator state machine isRecording was a writable stored property set by ContentView's 100ms polling loop. Any consumer outside that loop saw stale values when the main window was hidden. Replace with a computed property that reads directly from the coordinator's authoritative MeetingState. Also add MeetingMetadata.manual() factory to eliminate duplicate inline construction of manual session metadata. * Extract service initialization for headless operation TranscriptionEngine and other coordinator-owned services were created inside ContentView.task, making background recording impossible without a visible window. Add ensureServicesInitialized() on AppRuntime so services can be created early from AppDelegate. ContentView.task now only creates view-local services (KnowledgeBase, SuggestionEngine). * Add menu bar status item and popover NSStatusItem with two icon states: waveform.circle (idle) and waveform.circle.fill (recording). Icon updates reactively via withObservationTracking (zero wakeups when idle). Popover shows live recording status with elapsed timer computed from actual session start time, Start/Stop button with consent gate, Show App, and Quit. Uses NSPopover with NSHostingController for reliable sizing and focus behavior. --------- Co-authored-by: Szymon Sypniewicz <szymonsypniewicz@szymons-mac.mynet> Co-authored-by: Yazin's AI <github@mrfwd.com>
Newarr
pushed a commit
that referenced
this pull request
Mar 22, 2026
- Make cancel() async and await task completion to prevent data races (#1) - Move session-switch guard before backfillRefinedText to prevent stale writes (#3) - Cancel cleanup engine in teardownMeetingDetection (#4) - Add .pre-llm.md backup before overwriting Markdown with LLM sections (yazinsai#10) - Add safety documentation for nonisolated(unsafe) vars (#2) - Add unit tests for chunkRecords and parseResponse (#5) https://claude.ai/code/session_01QTKjQDQpoVqFrPJM8bp218
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
OpenOats shows a dock icon and requires a visible window to function. For a meeting transcription app that should listen for calls in the background, this means unnecessary desktop clutter. Users must keep the app window open or lose functionality.
Solution
Wire the menu bar components (from PR #3) into the app lifecycle and enable true background mode:
LSUIElement
Info.plistsetsLSUIElement=YES-- the app never shows a dock icon. This is the standard pattern used by Raycast, CleanShot X, Alfred, and Rectangle.Window close interception
Closing the main window calls
orderOut(nil)instead of destroying it. The window stays in memory for instant re-show via the menu bar popover's "Open OpenOats" button.NSApp.activate(ignoringOtherApps: true)ensures the window takes focus.Termination guard
Quitting while recording shows an
NSAlert:.idlestate, 30s timeout), then terminatesUses
NSApplication.TerminateReply.terminateLaterwith properreply(toApplicationShouldTerminate:)instead of a hardcoded delay.One-shot notification
First time the user closes the main window with auto-detect enabled, a macOS notification explains: "OpenOats is still running. Meeting detection is active." Shown once, tracked via UserDefaults. Requests notification authorization before sending.
Changed files
Info.plistLSUIElement = YESOpenOatsApp.swiftTest plan
PR 4 of 4 in the menu bar background mode series.
Depends on: #3 Add menu bar status item and popover